home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Libraries / PascalString / PascalStrings.cp next >
Encoding:
Text File  |  1994-11-11  |  4.2 KB  |  193 lines  |  [TEXT/MMCC]

  1. #include "PascalStrings.h"
  2.  
  3. // ----------------------------------------------------------------------------------------------------------------------
  4. // String copy routines
  5.  
  6. // Duff-style unrolled loop.  An invention of Tom Duff at Bellcore.  This macro generates some pretty unusual code that breaks
  7. // some compilers. On the other hand it has Dennis Ritchie's blessing as valid C code.
  8.  
  9. // Of course a simple BlockMove would do, but this is fun. Note that it is only efficient for small amounts of data, since we only
  10. // move one byte at a time. Longword moves would be more efficient.
  11.  
  12. #define LOOP8(n, s) {        \
  13.     register long __i;        \
  14.     __i = n >> 3;            \
  15.     switch(n & 7) {            \
  16.         do {                \
  17.             s;            \
  18.             case 7: s;        \
  19.             case 6: s;        \
  20.             case 5: s;        \
  21.             case 4: s;        \
  22.             case 3: s;        \
  23.             case 2: s;        \
  24.             case 1: s;        \
  25.             case 0: ;        \
  26.         } while (__i--);        \
  27.     }                    \
  28. }
  29.  
  30. static void DuffBlockMove (const unsigned char *source, unsigned char *dest, long n)
  31. {
  32.     #define MoveOneByte    *(dest++) = *(source++)
  33.     LOOP8(n, MoveOneByte);
  34. }
  35.  
  36. void StringCopy (const unsigned char *source, StringPtr dest)
  37. {
  38.     register    Byte            n = *source + 1;
  39.     #define    MoveOneByte    *(dest++) = *(source++)
  40.     LOOP8(n, MoveOneByte);
  41. }
  42.  
  43. void String2Text (const unsigned char *source, StringPtr dest)
  44. {
  45.     register Byte            n = *(source++);
  46.     #define    MoveOneByte    *(dest++) = *(source++)
  47.     LOOP8(n, MoveOneByte);
  48. }
  49.  
  50. // ----------------------------------------------------------------------------------------------------------------------
  51. // Implementation of the PascalString class.
  52.  
  53. PascalString::PascalString (const Str255& source)
  54. {
  55.     StringCopy(source, S);
  56. }
  57.  
  58. PascalString::PascalString ()
  59. {
  60.     S[0] = 0;
  61. }
  62.  
  63. PascalString& PascalString::operator= (const PascalString& source)
  64. {
  65.     StringCopy(source.S, S);
  66.     return *this;
  67. }
  68.  
  69. PascalString& PascalString::operator= (const Str255& source)
  70. {
  71.     StringCopy(source, S);
  72.     return *this;
  73. }
  74.  
  75. PascalString::PascalString (const PascalString& source)
  76. {
  77.     StringCopy(source.S, S);
  78. }
  79.  
  80. PascalString operator+ (const PascalString& p1, const PascalString& p2)
  81. {
  82.     PascalString    result;
  83.     unsigned char     len1 = p1.S[0];
  84.     unsigned char    len2 = p2.S[0];
  85.     
  86.     result = p1;
  87.     if (len1 + len2 <= 255) {                                            // Beware of overflows!
  88.         DuffBlockMove(p2.S + 1, result.S + len1 + 1, len2);
  89.         result.S[0] = len1 + len2;
  90.     }
  91.     else {
  92.         DuffBlockMove(p2.S + 1, result.S + len1 + 1, 255 - len1);
  93.         result.S[0] = 255;
  94.     }
  95.     
  96.     return result;
  97. }
  98.  
  99. PascalString& PascalString::operator+= (const PascalString& source)
  100. {
  101.     unsigned char    len1 = S[0];
  102.     unsigned char    len2 = source.S[0];
  103.     
  104.     if (len1 + len2 <= 255) {
  105.         DuffBlockMove(source.S + 1, S + len1 + 1, len2);
  106.         S[0] += len2;
  107.     }
  108.     else {
  109.         DuffBlockMove(source.S + 1, S + len1 + 1, 255 - len1);
  110.         S[0] = 255;
  111.     }
  112.     
  113.     return *this;
  114. }
  115.  
  116. PascalString& PascalString::operator+= (const Str255& source)
  117. {
  118.     unsigned char    len1 = S[0];
  119.     unsigned char    len2 = source[0];
  120.     
  121.     if (len1 + len2 <= 255) {
  122.         DuffBlockMove(source + 1, S + len1 + 1, len2);
  123.         S[0] += len2;
  124.     }
  125.     else {
  126.         DuffBlockMove(source + 1, S + len1 + 1, 255 - len1);
  127.         S[0] = 255;
  128.     }
  129.     
  130.     return *this;
  131. }
  132.  
  133. PascalString::PascalString (OSType source)
  134. {
  135.     Ptr        p = (Ptr) &source;
  136.  
  137.     S[0] = 4;
  138.     S[1] = p[0]; S[2] = p[1]; S[3] = p[2]; S[4] = p[3];
  139. }
  140.  
  141. PascalString::operator OSType ()
  142. {
  143.     OSType    result;
  144.     Ptr        p = (Ptr) &result;
  145.     
  146.     p[0] = S[0] > 0 ? S[1] : ' ';
  147.     p[1] = S[0] > 1 ? S[2] : ' ';
  148.     p[2] = S[0] > 2 ? S[3] : ' ';
  149.     p[3] = S[0] > 3 ? S[4] : ' ';
  150.     return result;
  151. }
  152.  
  153. PascalString::PascalString (long source)
  154. {
  155.     NumToString(source, S);
  156. }
  157.  
  158. PascalString::operator long ()
  159. {
  160.     long        result;
  161.     
  162.     StringToNum(S, &result);
  163.     return result;
  164. }
  165.  
  166. // PStringCmp works like IUCompString : it returns -1 if S1 < S2, 0 if S1 == S2  and +1 if S1 > S2.
  167. // PStringCmp has two advantages over IUCompString: first, it is probably much faster, although I didn't do any timing tests.
  168. // Second, it defines an ordering relation, i.e. it verifies PStringCmp(S1, S2) == -PStringCmp(S2, S1). IUCompString doesn't
  169. // (is it a bug or a feature?)
  170.     
  171. short PStringCmp (StringPtr S1, StringPtr S2)
  172. {
  173.     Byte            len1 = S1[0];
  174.     Byte            len2 = S2[0];
  175.     Byte            i = 1;
  176.     
  177.     while (true) {
  178.         if (i > len1 && i > len2)
  179.             return 0;
  180.         else if (i > len1)
  181.             return -1;
  182.         else if (i > len2)
  183.             return 1;
  184.         else {
  185.             if (S1[i] < S2[i])
  186.                 return -1;
  187.             else if (S1[i] > S2[i])
  188.                 return 1;
  189.             else
  190.                 i++;
  191.         }
  192.     }
  193. }